package pl.edu.agh;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static pl.edu.agh.Values.*;

public class Agent {
	ArrayList<Integer> history;
	/*
	 * zawiera strategie, wraz z ich aktualna ocena.
	 */
	HashMap<IStrategy, Float> ratedStrategies;
	HowCountStrategies howCount;

	public HashMap<IStrategy, Float> getStrategies() {
		return ratedStrategies;
	}

	public void rateStrategiesAfterStep(int actualyWent) {
		float newRate;
		for (java.util.Map.Entry<IStrategy, Float> entry : ratedStrategies
				.entrySet()) {
			newRate = rateStrategy(entry.getKey(), entry.getValue(),
					actualyWent);
			ratedStrategies.put(entry.getKey(), newRate);
		}
	}

	public ArrayList<Integer> getHistory() {
		return history;
	}

	@SuppressWarnings("unchecked")
	public Agent(ArrayList<Integer> history,
			List<Class<? extends IStrategy>> strategies, HowCountStrategies howCount) {
		this.history = (ArrayList<Integer>) history.clone();
		ratedStrategies = new HashMap<IStrategy, Float>();
		this.howCount = howCount;
		for (Class<? extends IStrategy> strategy : strategies) {
			try {
				addStrategy((IStrategy) strategy.newInstance());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void addToHistory(int count) {
		history.add(count);
	}

	public void addStrategy(IStrategy strategy) {
		ratedStrategies.put(strategy, 0F);
	}

	private float rateStrategy(IStrategy strategy, float lastRating,
			int actualyWent) {
		return Lambda * lastRating + (1 - Lambda)
				* (strategy.getLastPredictedNumber() - actualyWent);
	}

	public boolean decide() {
		// na poczatku kazdy chce isc, bo to dobry bar.
		boolean result = true;
		int goCount = 0;
		int stayCount = 0;

		if (howCount == HowCountStrategies.ALL) {
			for (java.util.Map.Entry<IStrategy, Float> entry : ratedStrategies
					.entrySet()) {

				if (entry.getKey().decide(history)) {
					goCount++;
				} else {
					stayCount++;
				}
			}

			if (goCount < stayCount) {
				result = false;
			}
			return result;
		}
		
		else if(howCount == HowCountStrategies.BEST)
		{
			float bestCount = Float.MAX_VALUE;
			IStrategy bestStrategy = null;
			
			for (java.util.Map.Entry<IStrategy, Float> entry : ratedStrategies
					.entrySet()) 
			{
				if(entry.getValue() < bestCount)
				{
					bestCount = entry.getValue();
					bestStrategy = entry.getKey();
				}
				
			}
			//System.out.println(bestStrategy);
			return bestStrategy.decide(history);
		}
		else
		{
			float go = 0;
			float stay = 0;
			
			for (java.util.Map.Entry<IStrategy, Float> entry : ratedStrategies
					.entrySet()) {

				if (entry.getKey().decide(history)) {
					go += 1/(entry.getValue() + 0.1); //+ 0.1 bo moze byc zero!
				} else {
					stay += 1/(entry.getValue() + 0.1);
				}
			}

			if (go < stay) {
				result = false;
			}
			return result;
		}
	}
}
